package com.bob.common;

import com.bob.common.bean.CommitInfo;
import com.bob.common.bean.DiffItem;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.TreeWalk;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

public class GitRepository {
    private static Log logger = new SystemStreamLog();


    private Git git;

    public GitRepository(String rootDir) throws IOException {
        logger.info(String.format("=== 根目录为:%s ", rootDir));
        git = initGit(rootDir);
    }

    /**
     * 初始化git仓库
     */
    private Git initGit(String rootDir) throws IOException {
        final String gitDirByRootDir = getGitDirByRootDir(rootDir);
        FileRepositoryBuilder builder = new FileRepositoryBuilder();
        Repository repository = builder.setGitDir(new File(gitDirByRootDir))
                .readEnvironment()
                .findGitDir()
                .build();
        try {
            return new Git(repository);
        } catch (NullPointerException e) {
            e.printStackTrace();
            throw new RuntimeException("=== 初始化git仓库初始化失败,GitDir : "+gitDirByRootDir+" 是否正确？");
        }
    }

    /**
     * 获取git目录
     */
    private static String getGitDirByRootDir(String rootDir) {
        return rootDir +File.separator+ ".git";
    }

    /**
     * 筛选 git log 信息
     */
    public List<CommitInfo> scanLog(String[] gitVersions) throws IOException, GitAPIException {
        Set<CommitInfo> commitInfoList = new HashSet<>();
        List<String> versionList = Arrays.stream(gitVersions).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        for (String version : versionList) {
            // 根据所需要查询的版本号查新ObjectId
            ObjectId objectId = git.getRepository().resolve(version);
            ObjectId objectId2 = git.getRepository().resolve(version);
            //根据版本号获取指定的详细记录
            Iterable<RevCommit> allCommitsLater = git.log().add(objectId).setMaxCount(1).call();
            if (allCommitsLater == null) {
                logger.error("该提交版本下无当前查询用户的提交记录");
                return new LinkedList<>();
            }
            Iterator<RevCommit> iter1 = allCommitsLater.iterator();
            Iterator<RevCommit> iter2 = git.log().add(objectId2).add(git.getRepository().resolve(version)).setMaxCount(2).call().iterator();
            if (iter2.hasNext()) {
                iter2.next();
            }
            if (iter1.hasNext()) {
                //提交对象
                RevCommit commit = iter1.next();
                CommitInfo commitInfo = new CommitInfo(commit);
                // 给存储库创建一个树的遍历器
                TreeWalk tw = new TreeWalk(git.getRepository());
                // 将当前commit的树放入树的遍历器中
                if (iter2.hasNext()) {
                    RevCommit commit2 = iter2.next();
                    if (commit2 != null) {
                        tw.addTree(commit2.getTree());
                    }
                }
                tw.addTree(commit.getTree());
                tw.setRecursive(true);
                RenameDetector rd = new RenameDetector(git.getRepository());
                rd.addAll(DiffEntry.scan(tw));
                //获取到详细记录结果集，在这里就能获取到一个版本号对应的所有提交记录
                List<DiffEntry> list = rd.compute();
                if (!list.isEmpty()) {
                    commitInfo.setDiffEntries(list);
                }
                commitInfoList.add(commitInfo);
                logger.info(String.format("=== git log scan : %s", commitInfo));
            }
        }
        DataStore.getDataStore().getCommitInfos().addAll(commitInfoList);
        return  DataStore.getDataStore().getCommitInfos();
    }

    public List<DiffItem> getDiffItems() {
        Set<DiffItem> diffEls = new HashSet<>(DataStore.getDataStore().getCommitInfos().size());
        for (CommitInfo commitInfo : DataStore.getDataStore().getCommitInfos()) {
            List<DiffEntry> diffEntries = commitInfo.getDiffEntries();
            diffForEach:
            for (DiffEntry entry : diffEntries) {
                String path = null;
                switch (entry.getChangeType()) {
                    case ADD:
                        path = entry.getNewPath();
                        break;
                    case COPY:
                        path = entry.getNewPath();
                        break;
                    case DELETE:
                        // path = entry.getOldPath();
                        continue diffForEach;
                    case MODIFY:
                        path = entry.getOldPath();
                        break;
                    case RENAME:
                        path = entry.getNewPath();
                        break;
                }

                logger.info(String.format("=== diff file path add ：%s", path));
                DiffItem diffItem = new DiffItem("", entry.getChangeType().name(), path);
                diffItem.setGroupName(this.getFileArtifactId(path));
                diffEls.add(diffItem);
            }
        }

        DataStore.getDataStore().getDiffItems().addAll(diffEls);
        return DataStore.getDataStore().getDiffItems();
    }

    /**
     * 获取文件所在项目 ArtifactId
     */
    private String getFileArtifactId(String filePath) {
        File file = new File(DataStore.getDataStore().getRootDir()+File.separator+filePath);
        // 变更文件的绝对路径 F:\dev\cczyz\cczyz\cczyz_web\src\main\webapp\public\vendor\html2canvas\html2canvas.min.v1.1.4.js
        final  String fileAbsolutePath = file.getAbsolutePath();
        Map<Integer,String> map = new TreeMap<>(Comparator.naturalOrder());
        Iterator<Map.Entry<String, String>> iterator = DataStore.getDataStore().getPomAbsolutePathRef().entrySet().iterator();
        while (iterator.hasNext()){
            // 直至得到文件对于子模块的相对路径
            Map.Entry<String, String> entry = iterator.next();
            String absolutePath = entry.getKey();
            String artifactId = entry.getValue();
            String p = fileAbsolutePath;
                p = p.replace(absolutePath, "");
            if(!p.contains(DataStore.getDataStore().getRootDir())){
                map.put(p.length(),artifactId);
            }

        }
        Map.Entry<Integer, String> next = map.entrySet().iterator().next();
        return next.getValue();
    }
}
